package service

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/nsqio/go-nsq"
	"go.uber.org/zap"
	"gsms/internal/conf"
	"gsms/internal/model"
	"gsms/internal/utils"
	"gsms/pkg/mcontext"
	"runtime"
)

type smsSendHandler struct {
	s *SmsService
}

type SmsMqBody struct {
	RequestID   string `json:"request_id"`
	Phone       string `json:"phone"`
	AppId       string `json:"appid"`
	MessageType string `json:"message_type" binding:"required"`
}

func failOver() {
	if r := recover(); r != nil {
		buf := make([]byte, 64<<10)
		buf = buf[:runtime.Stack(buf, false)]
		errInfo := fmt.Sprintf("worker: panic recovered: %s\n%s", r, buf)
		log := mcontext.Logger(context.Background())
		log.Error(errInfo)
	}
}

func (h *smsSendHandler) HandleMessage(m *nsq.Message) (err error) {
	defer failOver()
	if len(m.Body) == 0 {
		return nil
	}
	ctx := context.Background()
	log := mcontext.Logger(ctx)
	log.Info("send_sms start consume message...")
	var req = &SmsMqBody{}

	if err = json.Unmarshal(m.Body, req); err != nil {
		return err
	}

	if !utils.VerifyMobileFormat(req.Phone) {
		return errors.New(fmt.Sprintf("%s 手机号格式不合法", req.Phone))
	}
	if !conf.Conf.AllowedServers.IsAllowed(req.AppId) {
		log.Info(fmt.Sprintf("appid: %v not valid", req.AppId))
		return nil
	}

	sms := model.SmsVerify{To: req.Phone, From: req.AppId, VerifyType: req.MessageType,
		Status: model.SmsStatusUnused}
	smsHis := model.SmsHistory{
		RequestID: req.RequestID,
		To:        req.Phone,
		From:      req.AppId,
	}

	err = h.s.Send(ctx, sms, smsHis)
	if err == model.ErrDuplicate {
		log.Info(fmt.Sprintf("duplicated msg with requestId: %v", smsHis.RequestID))
		return nil
	} else if err != nil {
		log.Info("failure to send the sms...", zap.Error(err))
		return err
	}
	log.Info(fmt.Sprintf("sms was sent successfully: %v#%v", smsHis.RequestID, smsHis.To))
	return nil
}
